﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using McTools.Xrm.Connection;
using McTools.Xrm.Connection.WinForms;
using Microsoft.Xrm.Sdk;
using Tanguy.WinForm.Utilities.DelegatesHelpers;
using WebResourcesManager.AppCode;
using WebResourcesManager.DelegatesHelpers;
using WebResourcesManager.Forms;
using WebResourcesManager.UserControls;

namespace WebResourcesManager
{ 
    public sealed partial class MainForm : Form
    {
        #region Variables

        /// <summary>
        /// Connection Manager for Dynamics CRM 2011
        /// </summary>
        ConnectionManager cManager;

        /// <summary>
        /// Connection Statusbar for Dynamics CRM 2011
        /// </summary>
        CrmConnectionStatusBar ccsb;

        /// <summary>
        /// Crm organization service
        /// </summary>
        IOrganizationService service;

        /// <summary>
        /// Scripts Manager
        /// </summary>
        WebResourceManager wrManager;

        private FormHelper _formHelper;

        string newContent;

        #endregion Variables

        #region Constructor

        public MainForm()
        {
            InitializeComponent();
            try
            {
                // Displays version number
                Text += " (v" + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version + ")";

                // Instanciates the connection manager
                cManager = new ConnectionManager();
                cManager.ConnectionSucceed += cManager_ConnectionSucceed;
                cManager.ConnectionFailed += cManager_ConnectionFailed;
                cManager.StepChanged += cManager_StepChanged;
                cManager.RequestPassword += cManager_RequestPassword;
                _formHelper = new FormHelper(this, cManager);
                // Instanciates the connection status bar
                ccsb = new CrmConnectionStatusBar(cManager, _formHelper);
                Controls.Add(ccsb);
            }
            catch (Exception error)
            {
                MessageBox.Show(this, "Error while intializing application: " + error.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        bool cManager_RequestPassword(object sender, RequestPasswordEventArgs e)
        {
            return _formHelper.RequestPassword(e.ConnectionDetail);
        }

        #endregion Constructors

        #region Connection Handlers

        void cManager_StepChanged(object sender, StepChangedEventArgs e)
        {
            ccsb.SetMessage(e.CurrentStep);
        }

        void cManager_ConnectionFailed(object sender, ConnectionFailedEventArgs e)
        {
            ccsb.SetMessage(e.FailureReason);
            MessageBox.Show(e.FailureReason, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

        void cManager_ConnectionSucceed(object sender, ConnectionSucceedEventArgs e)
        {
            service = e.OrganizationService;

            ccsb.RebuildConnectionList();
            ccsb.SetConnectionStatus(true, e.ConnectionDetail);
            wrManager = new WebResourceManager(e.OrganizationService);

            if (e.Parameter != null && e.Parameter is CallBackAction)
            {
                CallBackAction cba = e.Parameter as CallBackAction;

                switch (cba.Action)
                {
                    case "LoadWebResources":
                        {
                            ccsb.SetMessage("Loading web resources...");
                            RetrieveWebResources();
                        }
                        break;
                    case "Update":
                        {
                            UpdateWebResources(false, cba.NodesToProcess);
                        }
                        break;
                    case "UpdateAndPublish":
                        {
                            UpdateWebResources(true, cba.NodesToProcess);
                        }
                        break;
                    case "Delete":
                        {
                            wrManager.DeleteWebResource(((WebResource)cba.NodesToProcess[0].Tag).WebResourceEntity);
                            tvWebResources.Nodes.Remove(cba.NodesToProcess[0]);
                        }
                        break;
                }
            }
            else if (e.Parameter != null && e.Parameter is Entity)
            {
                wrManager.CreateWebResource((Entity)e.Parameter);
                loadWebResourcesToolStripMenuItem_Click(null, null);
            }
        }

        #endregion

        #region Methods

        #region Web resources Loading

        void bwFillWebResources_DoWork(object sender, DoWorkEventArgs e)
        {
            RetrieveWebResources();
        }

        void bwFillWebResources_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                string errorMessage = CrmExceptionHelper.GetErrorMessage(e.Error, true);
                CommonDelegates.DisplayMessageBox(this, errorMessage, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            else
            {
                CommonDelegates.SetEnableState(tvWebResources, true);
            }

            SetWorkingState(false);
        }

        private void RetrieveWebResources()
        {
            EntityCollection scripts = wrManager.RetrieveWebResources();

            ccsb.SetMessage(string.Empty);

            TreeViewDelegates.ClearNodes(tvWebResources);

            foreach (Entity script in scripts.Entities)
            {
                WebResource wrObject = new WebResource(script);

                string[] nameParts = script["name"].ToString().Split('/');

                AddNode(nameParts, 0, tvWebResources, wrObject);
            }

            TreeViewDelegates.Sort(tvWebResources, new NodeSorter());
            TreeViewDelegates.ExpandAll(tvWebResources);
        }

        private void AddNode(string[] nameParts, int index, object parent, WebResource wrObject)
        {
            if (index == 0)
            {
                if (((TreeView)parent).Nodes.Find(nameParts[index], false).Length == 0)
                {
                    TreeNode node = new TreeNode(nameParts[index]);
                    node.Name = node.Text;

                    if (index == nameParts.Length - 1)
                    {
                        node.Tag = wrObject;

                        int imageIndex = ((OptionSetValue)wrObject.WebResourceEntity["webresourcetype"]).Value + 1;
                        node.ImageIndex = imageIndex;
                        node.SelectedImageIndex = imageIndex;
                    }
                    else
                    {
                            node.ImageIndex = 0;
                            node.SelectedImageIndex = 0;
                    }

                    TreeViewDelegates.AddNode((TreeView)parent, node);

                    AddNode(nameParts, index + 1, node, wrObject);
                }
                else
                {
                    AddNode(nameParts, index + 1, ((TreeView)parent).Nodes.Find(nameParts[index], false)[0], wrObject);
                }
            }
            else if (index < nameParts.Length)
            {
                if (((TreeNode)parent).Nodes.Find(nameParts[index], false).Length == 0)
                {
                    TreeNode node = new TreeNode(nameParts[index]);
                    node.Name = node.Text;

                    if (index == nameParts.Length - 1)
                    {
                        node.Tag = wrObject;
                        int imageIndex = ((OptionSetValue)wrObject.WebResourceEntity["webresourcetype"]).Value + 1;
                        node.ImageIndex = imageIndex;
                        node.SelectedImageIndex = imageIndex;
                    }
                    else
                    {
                        if (index == 0)
                        {
                            node.ImageIndex = 0;
                            node.SelectedImageIndex = 0;
                        }
                        else
                        {
                            node.ImageIndex = 1;
                            node.SelectedImageIndex = 1;
                        }
                    }

                    TreeViewDelegates.AddNode((TreeNode)parent, node);
                    AddNode(nameParts, index + 1, node, wrObject);
                }
                else
                {
                    AddNode(nameParts, index + 1, ((TreeNode)parent).Nodes.Find(nameParts[index], false)[0], wrObject);
                }
            }
        }

        #endregion Web resources Loading

        #region Main toolbar

        // START CRM WEBRESOURCES
        private void loadWebResourcesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (service == null)
            {
                tvWebResources.Nodes.Clear();

                _formHelper.AskForConnection(new CallBackAction() { Action = "LoadWebResources" });
            }
            else
            {
                tvWebResources.Nodes.Clear();

                SetWorkingState(true);

                BackgroundWorker bwFillWebResources = new BackgroundWorker();
                bwFillWebResources.DoWork += bwFillWebResources_DoWork;
                bwFillWebResources.RunWorkerCompleted += bwFillWebResources_RunWorkerCompleted;
                bwFillWebResources.RunWorkerAsync();
            }
        }

        private void updateCheckedWebResourcesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // Retrieve checked web resources
            List<TreeNode> nodesList = new List<TreeNode>();
            TreeViewHelper.GetNodes(nodesList, tvWebResources, true);

            if (service == null)
            {
                _formHelper.AskForConnection(new CallBackAction() { Action = "Update", NodesToProcess = nodesList });
            }
            else
            {
                UpdateWebResources(false, nodesList);
            }
        }

        private void updateAndPublishCheckedWebResourcesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // Retrieve checked web resources
            List<TreeNode> nodesList = new List<TreeNode>();
            TreeViewHelper.GetNodes(nodesList, tvWebResources, true);

            if (service == null)
            {
                _formHelper.AskForConnection(new CallBackAction() { Action = "UpdateAndPublish", NodesToProcess = nodesList });
            }
            else
            {
                UpdateWebResources(true, nodesList);
            }
        }
        //END CRM WEBRESOURCES

        //START DISK WEBRESOURCES
        private void loadWebResourcesToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            // Let the user decides where to find files
            FolderBrowserDialog fbd = new FolderBrowserDialog()
            {
                Description = "Select the folder where the scripts files are located",
                ShowNewFolderButton = true
            };

            if (fbd.ShowDialog() == DialogResult.OK)
            {
                tvWebResources.Nodes.Clear();

                DirectoryInfo di = new DirectoryInfo(fbd.SelectedPath);

                foreach (DirectoryInfo diChild in di.GetDirectories("*_", SearchOption.TopDirectoryOnly))
                {
                    TreeNode rootFolderNode = new TreeNode(diChild.Name);
                    rootFolderNode.ImageIndex = 0;

                    tvWebResources.Nodes.Add(rootFolderNode);

                    TreeViewHelper.CreateFolderStructure(rootFolderNode, diChild);
                }

                foreach (FileInfo fiChild in di.GetFiles("*.*", SearchOption.TopDirectoryOnly))
                {
                    TreeViewHelper.CreateWebResourceNode(fiChild, tvWebResources);
                }

                tvWebResources.ExpandAll();

                tvWebResources.TreeViewNodeSorter = new NodeSorter();
                tvWebResources.Sort();
            }
        }
        
        private void saveCheckedWebResourcesToDiskToolStripMenuItem_Click(object sender, EventArgs e)
        {
            List<TreeNode> nodes = new List<TreeNode>();
            TreeViewHelper.GetNodes(nodes, tvWebResources, true);

            SaveWebResourcesToDisk(nodes);
        }

        private void saveAllWebResourcesToDiskToolStripMenuItem_Click(object sender, EventArgs e)
        {
            List<TreeNode> nodes = new List<TreeNode>();
            TreeViewHelper.GetNodes(nodes, tvWebResources, false);

            SaveWebResourcesToDisk(nodes);
        }
        //END DISK WEBRESOURCES

        private void tsbNewRoot_Click(object sender, EventArgs e)
        {
            NewRootDialog nrd = new NewRootDialog();
            nrd.StartPosition = FormStartPosition.CenterParent;

            if (nrd.ShowDialog(this) == DialogResult.OK)
            {
                TreeNode rootNode = new TreeNode(nrd.RootName);
                rootNode.ImageIndex = 0;
                rootNode.SelectedImageIndex = 0;

                tvWebResources.Nodes.Add(rootNode);

                tvWebResources.TreeViewNodeSorter = new NodeSorter();
                tvWebResources.Sort();
            }
        }

        private void tsbDefineProxySettings_Click(object sender, EventArgs e)
        {
            _formHelper.EditProxySettings(this, cManager.ConnectionsList);
        }

        private void tsbAbout_Click(object sender, EventArgs e)
        {
            AboutForm aForm = new AboutForm();
            aForm.StartPosition = FormStartPosition.CenterParent;
            aForm.ShowDialog();
        }

        #region CodePlex

        private void tsbRate_Click(object sender, EventArgs e)
        {
            Process.Start("http://webresourcemanager.codeplex.com/releases");
        }

        private void tsbDiscuss_Click(object sender, EventArgs e)
        {
            Process.Start("http://webresourcemanager.codeplex.com/discussions");
        }

        private void tsbReportBug_Click(object sender, EventArgs e)
        {
            Process.Start("http://webresourcemanager.codeplex.com/WorkItem/Create");
        }

        private void tsbDonate_Click(object sender, EventArgs e)
        {
            string url = "";

            string business = "tanguy92@hotmail.com";  // your paypal email
            string description = "Donation%20for%20MSCRM%20Tools%20-%20WebResources%20Manager";            // '%20' represents a space. remember HTML!
            string country = "FR";                  // AU, US, etc.
            string currency = "EUR";                 // AUD, USD, etc.

            url += "https://www.paypal.com/cgi-bin/webscr" +
                "?cmd=" + "_donations" +
                "&business=" + business +
                "&lc=" + country +
                "&item_name=" + description +
                "&currency_code=" + currency +
                "&bn=" + "PP%2dDonationsBF";

            System.Diagnostics.Process.Start(url);

        }

        #endregion CodePlex

        #endregion Main toolbar

        #region TreeView Event handlers

        private void chkSelectAll_CheckedChanged(object sender, EventArgs e)
        {
            tvWebResources.AfterCheck -= new TreeViewEventHandler(tvWebResources_AfterCheck);

            foreach (TreeNode node in tvWebResources.Nodes)
                node.Checked = chkSelectAll.Checked;

            tvWebResources.AfterCheck += new TreeViewEventHandler(tvWebResources_AfterCheck);
        }

        private void tvWebResources_AfterCheck(object sender, TreeViewEventArgs e)
        {
            
            foreach (TreeNode node in e.Node.Nodes)
            {
                node.Checked = e.Node.Checked;
            }

            //tvWebResources.AfterCheck -= tvWebResources_AfterCheck;

            //TreeNode tempNode = e.Node;
            //while(tempNode.Parent != null)
            //{
            //    tempNode.Parent.Checked = true;
            //    tempNode = tempNode.Parent;
            //}

            //tvWebResources.AfterCheck += tvWebResources_AfterCheck;
        }

        private void tvWebResources_AfterSelect(object sender, TreeViewEventArgs e)
        {
            panelControl.Controls.Clear();

            if (tvWebResources.SelectedNode != null && tvWebResources.SelectedNode.Tag != null)
            {
                // Displays script content
                Entity script = ((WebResource)tvWebResources.SelectedNode.Tag).WebResourceEntity;
                UserControl ctrl = null;

                if (script.Contains("content") && script["content"] != null)
                {
                    switch (((OptionSetValue) script["webresourcetype"]).Value)
                    {
                        case 1:
                            ctrl = new CodeControl(script["content"].ToString(),
                                                   AppCode.Enumerations.WebResourceType.WebPage);
                            ((CodeControl) ctrl).WebResourceUpdated +=
                                new CodeControl.WebResourceUpdatedEventHandler(MainForm_WebResourceUpdated);
                            toolStripSeparatorMinifyJS.Visible = true;
                            tsbMinifyJS.Visible = false;
                            tsbPreviewHtml.Visible = true;
                            break;

                        case 2:
                            ctrl = new CodeControl(script["content"].ToString(),
                                                   AppCode.Enumerations.WebResourceType.Css);
                            ((CodeControl) ctrl).WebResourceUpdated +=
                                new CodeControl.WebResourceUpdatedEventHandler(MainForm_WebResourceUpdated);
                            break;
                        case 3:
                            ctrl = new CodeControl(script["content"].ToString(),
                                                   AppCode.Enumerations.WebResourceType.Script);
                            ((CodeControl) ctrl).WebResourceUpdated +=
                                new CodeControl.WebResourceUpdatedEventHandler(MainForm_WebResourceUpdated);
                            toolStripSeparatorMinifyJS.Visible = true;
                            tsbMinifyJS.Visible = true;
                            tsbPreviewHtml.Visible = false;
                            break;
                        case 4:
                            ctrl = new CodeControl(script["content"].ToString(),
                                                   AppCode.Enumerations.WebResourceType.Data);
                            ((CodeControl) ctrl).WebResourceUpdated +=
                                new CodeControl.WebResourceUpdatedEventHandler(MainForm_WebResourceUpdated);
                            break;
                        case 5:
                            ctrl = new ImageControl(script["content"].ToString(),
                                                    AppCode.Enumerations.WebResourceType.Png);
                            ((ImageControl) ctrl).WebResourceUpdated +=
                                new ImageControl.WebResourceUpdatedEventHandler(MainForm_WebResourceUpdated);
                            break;
                        case 6:
                            ctrl = new ImageControl(script["content"].ToString(),
                                                    AppCode.Enumerations.WebResourceType.Jpg);
                            ((ImageControl) ctrl).WebResourceUpdated +=
                                new ImageControl.WebResourceUpdatedEventHandler(MainForm_WebResourceUpdated);
                            break;
                        case 7:
                            ctrl = new ImageControl(script["content"].ToString(),
                                                    AppCode.Enumerations.WebResourceType.Gif);
                            ((ImageControl) ctrl).WebResourceUpdated +=
                                new ImageControl.WebResourceUpdatedEventHandler(MainForm_WebResourceUpdated);
                            break;
                        case 8:
                            ctrl = new UserControl();
                            break;
                        case 9:
                            ctrl = new CodeControl(script["content"].ToString(),
                                                   AppCode.Enumerations.WebResourceType.Xsl);
                            ((CodeControl) ctrl).WebResourceUpdated +=
                                new CodeControl.WebResourceUpdatedEventHandler(MainForm_WebResourceUpdated);
                            break;
                        case 10:
                            ctrl = new IconControl(script["content"].ToString());
                            ((IconControl) ctrl).WebResourceUpdated +=
                                new IconControl.WebResourceUpdatedEventHandler(MainForm_WebResourceUpdated);
                            break;
                    }
                }

                if (ctrl != null)
                {
                    ctrl.Size = panelControl.Size;
                    ctrl.Anchor = AnchorStyles.Bottom | AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
                    panelControl.Controls.Add(ctrl);

                    tsbSaveContent.Enabled = false;
                    tsbUpload.Enabled = true;
                    tsbPublish.Enabled = true;

                    lblResourceName.Text = script["name"].ToString();
                }
                else
                {
                    tsbSaveContent.Enabled = false;
                    tsbUpload.Enabled = false;
                    tsbPublish.Enabled = false;

                    toolStripSeparatorMinifyJS.Visible = false;
                    tsbMinifyJS.Visible = false;
                    tsbPreviewHtml.Visible = false;

                    lblResourceName.Text = string.Empty;
                }
            }
            else
            {
                // Clear script content
                tvWebResources.SelectedNode.ContextMenuStrip = null;

                tsbSaveContent.Enabled = false;
                tsbUpload.Enabled = false;
                tsbPublish.Enabled = false;
            }
        }

        private void tvWebResources_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                // Select the clicked node
                tvWebResources.SelectedNode = tvWebResources.GetNodeAt(e.X, e.Y);

                if (tvWebResources.SelectedNode != null)
                {
                    switch (tvWebResources.SelectedNode.ImageIndex)
                    {
                        case 0:
                            {
                                addNewFolderToolStripMenuItem.Enabled = true;
                                addNewWebResourceToolStripMenuItem.Enabled = true;
                                addNewEmptyWebResourceToolStripMenuItem.Enabled = true;
                                deleteToolStripMenuItem.Enabled = tvWebResources.SelectedNode.Nodes.Count == 0;
                                saveToCRMServerToolStripMenuItem.Enabled = false;
                                saveAndPublishToCRMServerToolStripMenuItem.Enabled = false;
                                propertiesToolStripMenuItem.Enabled = false;
                            }
                            break;
                        case 1:
                            {
                                addNewFolderToolStripMenuItem.Enabled = true;
                                addNewWebResourceToolStripMenuItem.Enabled = true;
                                addNewEmptyWebResourceToolStripMenuItem.Enabled = true;
                                deleteToolStripMenuItem.Enabled = tvWebResources.SelectedNode.Nodes.Count == 0;
                                saveToCRMServerToolStripMenuItem.Enabled = false;
                                saveAndPublishToCRMServerToolStripMenuItem.Enabled = false;
                                propertiesToolStripMenuItem.Enabled = false;
                            }
                            break;
                        default:
                            {
                                addNewFolderToolStripMenuItem.Enabled = false;
                                addNewWebResourceToolStripMenuItem.Enabled = false;
                                addNewEmptyWebResourceToolStripMenuItem.Enabled = false;
                                deleteToolStripMenuItem.Enabled = true;
                                saveToCRMServerToolStripMenuItem.Enabled = true;
                                saveAndPublishToCRMServerToolStripMenuItem.Enabled = true;
                                propertiesToolStripMenuItem.Enabled = true;
                            }
                            break;
                    }

                    if (tvWebResources.SelectedNode != null)
                    {
                        contextMenuStripTreeView.Show(tvWebResources, e.Location);
                    }
                }
            }
        }

        #endregion TreeView Event handlers

        #region Web resources toolbar handler

        private void tsbUpload_Click(object sender, EventArgs e)
        {
            ((IWebResourceControl)panelControl.Controls[0]).ReplaceWithNewFile();
        }

        private void tsbSaveContent_Click(object sender, EventArgs e)
        {
            string newContent = ((IWebResourceControl)panelControl.Controls[0]).GetBase64WebResourceContent();

            ((WebResource)tvWebResources.SelectedNode.Tag).WebResourceEntity["content"] = newContent;

            tsbSaveContent.Enabled = false;
            tvWebResources_AfterSelect(null, null);
        }

        private void tsbPublish_Click(object sender, EventArgs e)
        {
            if (tvWebResources.SelectedNode != null)
            {
                List<TreeNode> nodesList = new List<TreeNode>();
                nodesList.Add(tvWebResources.SelectedNode);

                if (service == null)
                {
                    _formHelper.AskForConnection(new CallBackAction() { Action = "UpdateAndPublish", NodesToProcess = nodesList });
                }
                else
                {
                    UpdateWebResources(true, nodesList);
                }
            }
        }

        #endregion Web resources toolbar handler

        #region Context Menu Strip Handlers

        private void addNewWebResourceToolStripMenuItem_Click(object sender, EventArgs e)
        {
            TreeNode selectedNode = tvWebResources.SelectedNode;
            TreeNode tempNode = selectedNode;

            string name = tempNode.Text;
            while (tempNode.Parent != null)
            {
                name = string.Format("{0}/{1}", tempNode.Parent.Text, name);
                tempNode = tempNode.Parent;
            }

            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Multiselect = true;
            ofd.Title = "Select file(s) for web resource(s)";
            
            if (ofd.ShowDialog(this) == DialogResult.OK)
            {
                foreach (string fileName in ofd.FileNames)
                {
                    FileInfo fi = new FileInfo(fileName);

                    Entity webResource = new Entity("webresource");
                    webResource["content"] = Convert.ToBase64String(File.ReadAllBytes(fileName));
                    webResource["webresourcetype"] = new OptionSetValue(GetTypeFromExtension(fi.Extension.Remove(0, 1)));
                    webResource["name"] = string.Format("{0}/{1}", name, fi.Name);
                    webResource["displayname"] = string.Format("{0}/{1}", name, fi.Name);
                    WebResource wr = new WebResource(webResource, fileName);

                    TreeNode node = new TreeNode(fi.Name);
                    node.ImageIndex = GetImageIndexFromExtension(fi.Extension.Remove(0, 1));
                    node.SelectedImageIndex = node.ImageIndex;
                    node.Tag = wr;

                    selectedNode.Nodes.Add(node);

                    selectedNode.Expand();
                }
            }

            tvWebResources.TreeViewNodeSorter = new NodeSorter();
            tvWebResources.Sort();
        }

        private int GetTypeFromExtension(string ext)
        {
            switch (ext)
            {
                case "htm":
                case "html":
                    return 1;
                case "css":
                    return 2;
                case "js":
                    return 3;
                case "xml":
                    return 4;
                case "png":
                    return 5;
                case "jpg":
                case "jpeg":
                    return 6;
                case "gif":
                    return 7;
                case "xap":
                    return 8;
                case "xsl":
                    return 9;
                default:
                    return 10;
            }
        }

        private int GetImageIndexFromExtension(string ext)
        {
            switch (ext)
            {
                case "htm":
                case "html":
                    return 2;
                case "css":
                    return 3;
                case "js":
                    return 4;
                case "xml":
                    return 5;
                case "png":
                    return 6;
                case "jpg":
                case "jpeg":
                    return 7;
                case "gif":
                    return 8;
                case "xap":
                    return 9;
                case "xsl":
                    return 10;
                default:
                    return 11;
            }
        }

        private void addNewFolderToolStripMenuItem_Click(object sender, EventArgs e)
        {
            TreeNode selectedNode = tvWebResources.SelectedNode;

            NewFolderDialog nfd = new NewFolderDialog();
            nfd.StartPosition = FormStartPosition.CenterParent;

            if (nfd.ShowDialog(this) == DialogResult.OK)
            {

                TreeNode node = new TreeNode(nfd.FolderName);
                node.ImageIndex = 1;
                node.SelectedImageIndex = 1;

                selectedNode.Nodes.Add(node);

                tvWebResources.SelectedNode = node;
            }

            tvWebResources.TreeViewNodeSorter = new NodeSorter();
            tvWebResources.Sort();
        }

        private void saveToCRMServerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // If no item is selected, return
            if (tvWebResources.SelectedNode == null)
                return;

            // Retrieve checked web resources
            List<TreeNode> nodesList = new List<TreeNode>();
            TreeViewHelper.GetNodes(nodesList, tvWebResources, true);

            // Uncheck all items
            foreach (TreeNode node in nodesList)
            {
                node.Checked = false;
            }

            // Check the selected item
            tvWebResources.SelectedNode.Checked = true;

            
            if (service == null)
            {
                // Call for connection
                _formHelper.AskForConnection(new CallBackAction() { Action = "Update", NodesToProcess = new List<TreeNode> { tvWebResources.SelectedNode } });
            }
            else
            {
                UpdateWebResources(false, new List<TreeNode> { tvWebResources.SelectedNode });
            }
        }

        private void saveAndPublishToCRMServerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // If no item is selected, return
            if (tvWebResources.SelectedNode == null)
                return;

            // Retrieve checked web resources
            List<TreeNode> nodesList = new List<TreeNode>();
            TreeViewHelper.GetNodes(nodesList, tvWebResources, true);

            // Uncheck all items
            foreach (TreeNode node in nodesList)
            {
                node.Checked = false;
            }

            // Check the selected item
            tvWebResources.SelectedNode.Checked = true;


            if (service == null)
            {
                // Call for connection
                _formHelper.AskForConnection(new CallBackAction() { Action = "Update", NodesToProcess = new List<TreeNode> { tvWebResources.SelectedNode } });
            }
            else
            {
                UpdateWebResources(true, new List<TreeNode> { tvWebResources.SelectedNode });
            }
        }

        private void deleteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // Uncheck all items
            foreach (TreeNode node in tvWebResources.Nodes)
            {
                node.Checked = false;
            }

            // Check the selected item
            tvWebResources.SelectedNode.Checked = true;

            TreeNode selectedNode = tvWebResources.SelectedNode;

            if (selectedNode.ImageIndex > 1)
            {
                if (DialogResult.Yes == MessageBox.Show(this,
                    "This web resource will be deleted from the Crm server if you are connected and this web resource exists.\r\nAre you sure you want to delete this web resource?",
                    "Question",
                    MessageBoxButtons.YesNo,
                    MessageBoxIcon.Question))
                {
                    WebResource wr = selectedNode.Tag as WebResource;

                    if (wr != null && wr.WebResourceEntity != null && wr.WebResourceEntity.Id != Guid.Empty)
                    {
                        List<TreeNode> nodesList = new List<TreeNode>();
                        nodesList.Add(selectedNode);

                        if (service == null)
                        {
                            _formHelper.AskForConnection(new CallBackAction() { Action = "Delete", NodesToProcess = nodesList });
                        }
                        else
                        {
                            DeleteWebResource(nodesList);
                        }
                    }
                    else
                    {
                        tvWebResources.Nodes.Remove(selectedNode);
                    }
                }
            }
            else
            {
                tvWebResources.Nodes.Remove(selectedNode);
            }
        }

        private void propertiesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // Uncheck all items
            foreach (TreeNode node in tvWebResources.Nodes)
            {
                node.Checked = false;
            }

            // Check the selected item
            tvWebResources.SelectedNode.Checked = true;

            TreeNode selectedNode = tvWebResources.SelectedNode;

            UpdateForm form = new UpdateForm((WebResource)selectedNode.Tag, service);
            form.StartPosition = FormStartPosition.CenterParent;

            if (form.ShowDialog(this) == DialogResult.OK)
            {
                selectedNode.Tag = form.WebRessource;
            }
        }

        #endregion Context Menu Strip Handlers

        #region Other methods

        private void SaveWebResourcesToDisk(List<TreeNode> nodes)
        {
            FolderBrowserDialog fbd = new FolderBrowserDialog();

            if (fbd.ShowDialog() == DialogResult.OK)
            {
                foreach (TreeNode node in nodes)
                {
                    if (node.Tag != null && ((WebResource)node.Tag).WebResourceEntity != null)
                    {
                        Entity webResource = ((WebResource)node.Tag).WebResourceEntity;

                        if (webResource.Contains("content") && webResource["content"].ToString().Length > 0)
                        {
                            string[] partPath = webResource["name"].ToString().Split('/');
                            string path = fbd.SelectedPath;

                            for (int i = 0; i < partPath.Length - 1; i++)
                            {
                                path = Path.Combine(path, partPath[i]);

                                if (!Directory.Exists(path))
                                    Directory.CreateDirectory(path);
                            }

                            path = Path.Combine(path, partPath[partPath.Length - 1]);
                            byte[] bytes = Convert.FromBase64String(webResource["content"].ToString());
                            File.WriteAllBytes(path, bytes);
                        }
                    }
                }
            }
        }
        
        void MainForm_WebResourceUpdated(object sender, WebResourceUpdatedEventArgs e)
        {
            tsbSaveContent.Enabled = e.IsDirty;
        }

        private void UpdateWebResources(bool publish, List<TreeNode> nodes)
        {
            List<Entity> webResources = new List<Entity>();
            foreach (TreeNode node in nodes)
            {
                if (node.Tag != null && ((WebResource)node.Tag).WebResourceEntity != null)
                {
                    webResources.Add(((WebResource)node.Tag).WebResourceEntity);
                }
            }

            SetWorkingState(true);

            object[] parameters = new object[] { webResources, publish };
            
            BackgroundWorker bw = new BackgroundWorker();
            bw.DoWork += new DoWorkEventHandler(bw_DoWork);
            bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
            bw.RunWorkerAsync(parameters);
        }

        void bw_DoWork(object sender, DoWorkEventArgs e)
        {
            WebResourceManager wrManager = new WebResourceManager(service);
            List<Guid> idsToPublish = new List<Guid>();

            foreach (Entity wr in ((List<Entity>)((object[])e.Argument)[0]))
            {
                ccsb.SetMessage("Updating " + wr["name"].ToString() + "...");

                wr.Id = wrManager.UpdateWebResource(wr);

                idsToPublish.Add(wr.Id);
            }

            // if publish
            if ((bool)((object[])e.Argument)[1])
            {
                ccsb.SetMessage("Publishing web resources...");

                wrManager.PublishWebResources(idsToPublish);
            }
        }

        void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                ccsb.SetMessage("");
            }
            else
            {
                MessageBox.Show(this, "An error occured: " + e.Error.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            SetWorkingState(false);
        }

        void SetWorkingState(bool working)
        {
            tsbNewRoot.Enabled = !working;
            tsddCrmMenu.Enabled = !working;
            tsddFileMenu.Enabled = !working;
            tvWebResources.Enabled = !working;
            chkSelectAll.Enabled = !working;
            toolStripScriptContent.Enabled = !working;

            tsbSaveContent.Enabled = false;
            var selectedNode = tvWebResources.SelectedNode;
            if (selectedNode != null)
            {
                tsbUpload.Enabled = selectedNode.Tag != null;
                tsbPublish.Enabled = selectedNode.Tag != null;
            }

            Cursor = working ? Cursors.WaitCursor : Cursors.Default;
        }

        void DeleteWebResource(List<TreeNode> nodes)
        {
            SetWorkingState(true);
            ccsb.SetMessage("Deleting web resource...");

            BackgroundWorker bwDelete = new BackgroundWorker();
            bwDelete.DoWork += new DoWorkEventHandler(bwDelete_DoWork);
            bwDelete.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bwDelete_RunWorkerCompleted);
            bwDelete.RunWorkerAsync(((WebResource)nodes[0].Tag).WebResourceEntity);
        }

        void bwDelete_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                ccsb.SetMessage("");
            }
            else
            {
                MessageBox.Show(this, "An error occured: " + e.Error.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            SetWorkingState(false);
        }

        void bwDelete_DoWork(object sender, DoWorkEventArgs e)
        {
            wrManager.DeleteWebResource((Entity)e.Argument);
        }

        #endregion Other methods

        private void tsbMinifyJS_Click(object sender, EventArgs e)
        {
            if (DialogResult.Yes ==
                MessageBox.Show(this,
                                "Are you sure you want to compress this script? After saving the compressed script, you won't be able to retrieve original content",
                                "Question", MessageBoxButtons.YesNo, MessageBoxIcon.Question))
                ((CodeControl) panelControl.Controls[0]).MinifyJs();
        }

        #endregion Methods

        private void hTMLToolStripMenuItem_Click(object sender, EventArgs e)
        {
            CreateEmptyWebResource("html", tvWebResources.SelectedNode);
        }

        private void cSSToolStripMenuItem_Click(object sender, EventArgs e)
        {
            CreateEmptyWebResource("css", tvWebResources.SelectedNode);
        }

        private void scriptToolStripMenuItem_Click(object sender, EventArgs e)
        {
            CreateEmptyWebResource("js", tvWebResources.SelectedNode);
        }

        private void dataToolStripMenuItem_Click(object sender, EventArgs e)
        {
            CreateEmptyWebResource("xml", tvWebResources.SelectedNode);
        }

        private void xSLTToolStripMenuItem_Click(object sender, EventArgs e)
        {
            CreateEmptyWebResource("xslt", tvWebResources.SelectedNode);
        }

        private void CreateEmptyWebResource(string extension, TreeNode callerNode)
        {
            var nwrDialog = new NewWebResourceDialog(extension);
            if(nwrDialog.ShowDialog() == DialogResult.OK)
            {
                var tempNode = callerNode;
                string name = callerNode.Text;
                while (tempNode.Parent != null)
                {
                    name = string.Format("{0}/{1}", tempNode.Parent.Text, name);
                    tempNode = tempNode.Parent;
                }

                var webResource = new Entity("webresource");
                webResource["content"] = "";
                webResource["webresourcetype"] = new OptionSetValue(GetTypeFromExtension(extension));
                webResource["name"] = string.Format("{0}/{1}", name, nwrDialog.WebResourceName);
                var wr = new WebResource(webResource, null);

                var node = new TreeNode(nwrDialog.WebResourceName);
                node.ImageIndex = GetImageIndexFromExtension(extension);
                node.SelectedImageIndex = node.ImageIndex;
                node.Tag = wr;

                callerNode.Nodes.Add(node);
                callerNode.Expand();
            }
        }

        private void TsbPreviewHtmlClick(object sender, EventArgs e)
        {
            string content = ((IWebResourceControl) panelControl.Controls[0]).GetBase64WebResourceContent();

            var wpDialog = new WebPreviewDialog(content);
            wpDialog.ShowDialog();
        }
    }
}
